/*******************************************************************************
 * Copyright (c) 2013 Zero Square LLC.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Zero Square LLC. Version 1
 * which accompanies this distribution
 ******************************************************************************/
package com.zsqr.dashboard.services.impl;

import java.util.ArrayList;
import java.util.Collection;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;

import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import java.util.ResourceBundle;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;
import org.primefaces.component.inputtext.InputText;

import com.zsqr.dashboard.dao.UserDao;
import com.zsqr.dashboard.domain.UserEntity;
import com.zsqr.dashboard.services.UserService;

/**
 * Provide service method to work with user data and entity
 * @author Saurabh
 *
 */
public class UserServiceImpl implements UserService,UserDetailsService{

	
	private UserDao userDao; 
	
	/**
	 * Create user - persist to database
	 * @param userEntity
	 * @return true if success
	 */
	public boolean createUser(UserEntity userEntity){
		if(!userDao.checkAvailable(userEntity.getUserName())){
			
			FacesMessage message = constructErrorMessages
				(String.format("User Name '%s' is not available", userEntity.getUserName()),null);			
			getFacesContext().addMessage(null, message);			
			return false;			
		}
		
		try{
			
			userDao.save(userEntity);
		
		}catch(Exception e){
			FacesMessage message = constructFatalMessages(e.getMessage(), null);
			getFacesContext().addMessage(null, message);
			return false;
		}
		
		return true;
	}
	
	/**
	 * Check user name availability
	 * @param ajax event
	 * @return
	 */
	 public boolean checkAvailable(AjaxBehaviorEvent event) {
	 	InputText inputText = (InputText) event.getSource();
	 	String value = (String) inputText.getValue();
	 	boolean available = userDao.checkAvailable(value);
	 	if (!available) {
	 		FacesMessage message = constructErrorMessages(null, String.format(getMessageBundle().getString("userExistsMsg"), value));
	 						getFacesContext().addMessage(event.getComponent().getClientId(), message);
			} else {
				FacesMessage message = consturctInfoMessages(null, String.format(getMessageBundle().getString("userAvailableMsg"), value));
				getFacesContext().addMessage(event.getComponent().getClientId(), message);
			}
		
				return available;
		}
	
	/*
	 * Construct user detail instance required by Spring Security
	 * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String)
	 */
	public UserDetails loadUserByUsername(String userName)throws UsernameNotFoundException{
		UserEntity user = userDao.loadUserByUserName(userName);
		if(user == null)
		{
			throw new UsernameNotFoundException(String.format(getMessageBundle().getString("badCredentials"), userName));
			//throw new UsernameNotFoundException(String.format("User does not exist '%s'", userName));
		}
		Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
		authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
		
		User userDetails = new User(user.getUserName(), user.getPassword(),authorities);
		return userDetails;
	}
	
	/**
     * Retrieves full User record from database by user name
     * 
     * @param userName
     * @return UserEntity
     */
    public UserEntity loadUserEntityByUsername(String userName) {
            return userDao.loadUserByUserName(userName);
    }
	 
	public boolean updateUser(UserEntity userEntity){
	        if(validateUser(userEntity) == true)
	        {
	        	if(userDao.save(userEntity)!= null)
	        		return true;
				else
					return false;
	        }
	        else
	        	return false;
		  
	}
	public boolean validateUser(UserEntity userEntity){
		userEntity = userDao.loadUserByUserName(userEntity.getUserName());
		if(userEntity == null)
			return false;
		return true;
	}
	
	public boolean validateLogin(UserEntity userEntity){
		UserEntity curUser = null;
		curUser = userDao.loadUserByUserName(userEntity.getUserName());
		if(curUser == null)
			return false;
		else if( (curUser.getUserName().equals(userEntity.getUserName()) )  && (curUser.getPassword().equals(userEntity.getPassword())) )
		{
			return true;
		}
		else
			return false;
		
		
	}
	
	protected FacesMessage constructErrorMessages(String message,String detail){
		return new FacesMessage(FacesMessage.SEVERITY_ERROR, message, detail);
		}
	
	protected FacesMessage consturctInfoMessages (String message,String detail){
		return new FacesMessage(FacesMessage.SEVERITY_INFO, message, detail);
	}
	
	protected FacesMessage constructFatalMessages(String message,String detail){
		return new FacesMessage(FacesMessage.SEVERITY_FATAL, message, detail);
	}
	
	protected FacesContext getFacesContext()
	{
		return FacesContext.getCurrentInstance();
	}
	
	protected ResourceBundle getMessageBundle() {
		return ResourceBundle.getBundle("message-labels");
		}

	public UserDao getUserDao() {
		return userDao;
	}
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	
}
